#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "err.hpp"

using namespace std;

static void usage(string proc)
{
    std::cout<<"Usage:\n\t"<<proc<<"port\n"<<std::endl;
}
//./udp_client serverip serverport
int main(int argc, char *argv[])
{
    if(argc!=3)
    {
        usage(argv[0]);
        exit(USAGE_ERR);
    }
    std::string serverip = argv[1];
    uint16_t serverport = atoi(argv[2]);

    //1.创建套接字
    int sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock<0)
    {
        cerr<<"socket error: "<<strerror(errno)<<endl;
        exit(SOCKET_ERR);
    }

    //2.客户端要bind，但不需要自己bind，因为client要让OS自动给用户进行bind
    //3.客户端也不需要listen，服务器listen
    //4.要不要accept?不需要

    //5.向服务器发起连接
    //int connect(int sockfd,const struct sockaddr* addr,socklen_t addrlen)
    struct sockaddr_in server;
    memset(&server,0,sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(serverport);
    //将字符串ip地址转换
    inet_aton(serverip.c_str(),&(server.sin_addr));
    
    int cnt=5;
    while(connect(sock,(struct sockaddr*)&server,sizeof(server))!=0)
    {
        sleep(1);
        cout<<"正在给你尝试重连，重连次数还有: "<<cnt--<<endl;
        if(cnt<=0) break;
    }
    if(cnt<=0)
    {
        cerr<<"连接失败..."<<endl;
        exit(CONNECT_ERR);
    }
    //6.连接成功，给服务器发送需求
    char buffer[1024];
    while(true)
    {
        string line;
        cout<<"Enter>> ";
        getline(cin,line);

        write(sock,line.c_str(),line.size());

        //读取服务器返回的结果
        ssize_t s = read(sock,buffer,sizeof(buffer)-1);
        if(s>0)
        {
            buffer[s]=0;
            cout<<"server echo >>"<<buffer<<endl;
        }
        else if(s==0)//读到文件结尾
        {
            cerr<<"server quit"<<endl;
            break;
        }
        else
        {
            cerr<<"read error: "<<strerror(errno)<<endl;
            break;
        }
    }
    close(sock);
    return 0;

}